package com.demo.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.demo.bean.AjaxResult;
import com.demo.dto.User;
import com.demo.service.AmqSenderService;
import com.demo.service.UserService;
import com.demo.util.CommonsUtil;
import com.demo.util.ExportExcelUtil;
import com.demo.util.RedisUtil;
import com.demo.vo.UserVO;
import org.apache.commons.io.FileUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Controller
@RequestMapping(value = "demo")
public class TestController {
    @Reference
    private UserService userService;

    @Reference
    private AmqSenderService amqSenderService;

    @Autowired
    private RedisUtil redisUtil;


    /**
     * 删除用户通过id POST方式
     *
     * @param userVO
     * @return
     */
    @RequestMapping(value = "deleteUserPost", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult deleteUserById(@RequestBody UserVO userVO) {
        try {
            return new AjaxResult(userService.deleteUserById(userVO.getUserId()));
        } catch (Exception e) {
            e.printStackTrace();
            return new AjaxResult(e.getMessage(), CommonsUtil.ERROR);
        }
    }


    /**
     * 测试跳转admin.jsp
     * * 实际返回的是/views/admin.jsp  InternalResourceViewResolver  自动加上了前后缀
     *
     * @return
     */
    @RequestMapping(value = "admin", method = RequestMethod.GET)
    public String admin() {
        return "admin";
    }


    /**
     * 删除用户通过id GET方式
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "deleteUserGet", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult deleteUserById(Long id) {
        try {

            User user = new User();
            user.setId(id);
            user.setAccountName("demoUser");
            user.setAge(11);
            user.setName("冯亚敏");
            user.setPassword("root");

            //测试消息mq
            amqSenderService.sendQuenMsg(user);
            amqSenderService.sendTopicMsg(user);

            int resultNum;
            //redis有则直接获取不在调用dubbo服务调用后台 减少调用次数
            if (redisUtil.hasKey(id.toString())) {
                resultNum = Integer.parseInt(redisUtil.get(id.toString()).toString());
            } else {
                resultNum = userService.deleteUserById(id);
            }
            return new AjaxResult(resultNum);
        } catch (Exception e) {
            e.printStackTrace();
            return new AjaxResult(e.getMessage(), CommonsUtil.ERROR);
        }
    }


    /**
     * 登录
     *
     * @param user
     * @param model
     * @return
     */
    @RequestMapping("/dologin")
    public String dologin(User user, Model model) {
        String info = loginUser(user);
        if (!"SUCC".equals(info)) {
            model.addAttribute("failMsg", "User does not exist or password error!");
            return "fail";
        } else {
            model.addAttribute("successMsg", "login Success!");
            model.addAttribute("name", user.getAccountName());
            return "success";
        }
    }


    /**
     * 退出
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/logout")
    public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException {
        Subject subject = SecurityUtils.getSubject();
        if (subject != null) {
            subject.logout();
        }
        response.sendRedirect("/index.jsp");
    }


    private String loginUser(User user) {
        if (isRelogin(user)) return "SUCC";
        return shiroLogin(user);
    }

    /**
     * shiro验证
     *
     * @param user
     * @return
     */
    private String shiroLogin(User user) {
        UsernamePasswordToken token = new UsernamePasswordToken(user.getAccountName(), user.getPassword().toCharArray(), null);
        token.setRememberMe(true);
        try {
            SecurityUtils.getSubject().login(token);
        } catch (UnknownAccountException ex) {
            return "User does not exist or password error!";
        } catch (IncorrectCredentialsException ex) {
            return "User does not exist or password error!";
        } catch (AuthenticationException ex) {
            ex.printStackTrace();
            return ex.getMessage();
        } catch (Exception ex) {
            ex.printStackTrace();
            return "Internal error, please try again!";
        }
        return "SUCC";
    }

    private boolean isRelogin(User user) {
        Subject us = SecurityUtils.getSubject();
        if (us.isAuthenticated()) {
            return true;
        }
        return false;
    }

    @RequestMapping("/register")
    @ResponseBody
    public AjaxResult register(User user, Model model) {
        if ((!"".equals(user.getAccountName())) && user.getAccountName() != null) {
            //默认注册的用户都是user权限
            user.setRole("user");
            User userDb = userService.selectUserByAccountName(user.getAccountName());
            if (userDb != null) return new AjaxResult("user exist!", CommonsUtil.ERROR);
            userService.insertUser(user);
            return new AjaxResult("register Success!");
        }
        return new AjaxResult("paramErr!", CommonsUtil.ERROR);
    }


    /**
     * 导出活动执行查询结果
     * @param response
     * @return
     */
    @RequestMapping("excelExpot")
    @ResponseBody
    public AjaxResult exportActivityExecuteQueryResult(HttpServletResponse response) {
        // 获取导出需要的数据
        List<User> users = userService.selectUsers();
        if (users == null || users.size() <= 0) {
            return new AjaxResult("当前没有可导出的查询信息", CommonsUtil.ERROR);
        }
        String title = "用户详细信息导出";
        Integer[] widths = new Integer[]{70,40, 60, 60, 30};
        String[] rowsName = new String[]{"账户名", "邮箱", "ID", "姓名", "角色"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        for (User user : users) {
            Object[] objs = null;
            objs = new Object[rowsName.length];
            objs[0] = user.getAccountName();
            objs[1] = user.getEmail();
            objs[2] = user.getId();
            objs[3] = user.getName();
            objs[4] = user.getRole();
            dataList.add(objs);
        }
        ExportExcelUtil ex = new ExportExcelUtil(title, rowsName, widths, dataList);
        XSSFWorkbook workbook = ex.export();
        if (workbook != null) {
            try {
                String fileName = "Excel-" + String.valueOf(System.currentTimeMillis()).substring(4, 13) + ".xls";
                String headStr = "attachment; filename=\"" + fileName + "\"";
                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                response.setHeader("Content-Disposition", headStr);
                OutputStream out = response.getOutputStream();
                workbook.write(out);
                out.flush();
                workbook.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }




    /**
     * 上传文件
     * @param viewFile
     * @param session
     * @return
     */
    @RequestMapping(value = "uploadFile", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult uploadAddView(@RequestBody MultipartFile viewFile, HttpSession session) {
        try {
            //判断是否存在文件和对文件的格式进行判断
            if (viewFile == null) {
                throw new RuntimeException("请选择需要补充的文件");
            } else if (!CommonsUtil.ALLOW_ADDFILE_SUFFIX.contains(viewFile.getOriginalFilename().substring(viewFile.getOriginalFilename().lastIndexOf(".")))) {
                throw new RuntimeException("文件格式错误,目前支持的后缀格式为:" + CommonsUtil.ALLOW_ADDFILE_SUFFIX.toString());
            }

            //获取保存上传文件的file文件夹绝对路径
            String path = session.getServletContext().getRealPath(CommonsUtil.WEB_FILE_UPLOAD_PATH);
            File dir = new File(path);
            if (!dir.exists()) {
                boolean flag = dir.mkdirs();
            }
            //获取上传文件名
            String originFileName = viewFile.getOriginalFilename();
            String fileName = UUID.randomUUID() + viewFile.getOriginalFilename().substring(viewFile.getOriginalFilename().lastIndexOf("."));
            File file = new File(path, fileName);
            viewFile.transferTo(file);
            return new AjaxResult("上传成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new AjaxResult(e.getMessage(), CommonsUtil.ERROR);
        }
    }


    /**
     * 删除文件
     *
     * @param fileName 文件
     * @return
     */
    @RequestMapping(value = "deleteAddView", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult deleteAddView(String fileName, HttpSession session) {
        try {
            //获取保存上传文件的file文件夹绝对路径
            String path = session.getServletContext().getRealPath(CommonsUtil.WEB_FILE_UPLOAD_PATH);
            File file = new File(path, fileName);
            //如果文件存在则删除文件
            if (file.exists()) {
                file.delete();
            } else {
                throw new RuntimeException("要删除的文件不存在");
            }
            return new AjaxResult("删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new AjaxResult(e.getMessage(), CommonsUtil.ERROR);
        }
    }


    /**
     * 下载文件
     *
     * @param fileName 文件名称
     * @return
     */
    @RequestMapping(value = "downloadAddView", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult downloadAddView(String fileName, HttpSession session, HttpServletResponse response, Integer resultId) {
        try {
            if (fileName != null) {
                //获取保存上传文件的file文件夹绝对路径
                String path = session.getServletContext().getRealPath(CommonsUtil.WEB_FILE_UPLOAD_PATH);
                File file = new File(path, fileName);
                OutputStream out = null;
                if (file.exists()) {
                    //设置下载完毕不打开文件
                    response.setContentType("application/force-download");
                    //设置文件名
                    response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
                    out = response.getOutputStream();
                    out.write(FileUtils.readFileToByteArray(file));
                    out.flush();
                } else {
                    throw new RuntimeException("文件不存在");
                }
            } else {
                throw new RuntimeException("文件名不能为空");
            }
            return new AjaxResult("下载成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new AjaxResult(e.getMessage(), CommonsUtil.ERROR);
        }
    }




}
